package org.liufree.xmindparser;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriteConfig;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;
import lombok.Cleanup;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentException;
import org.liufree.xmindparser.pojo.*;

/**
 * @author liufree liufreeo@gmail.com
 * XmindParser
 *  解析主体
 * 2020/4/27 14:05
 */
public class XmindParser {

    public static final String SEMMA = ",";
    public static final String xmindZenJson = "content.json";
    public static final String xmindLegacyContent = "content.xml";
    public static final String xmindLegacyComments = "comments.xml";

    /**
     * 解析脑图文件，返回content整合后的内容
     *
     * @param xmindFile
     * @return
     * @throws IOException
     * @throws ArchiveException
     * @throws DocumentException
     */
    public static String parseJson(String xmindFile) throws IOException, ArchiveException, DocumentException {
        String res = ZipUtils.extract(xmindFile);

        String content = null;
        if (isXmindZen(res, xmindFile)) {
            content = getXmindZenContent(xmindFile,res);
        } else {
            content = getXmindLegacyContent(xmindFile,res);
        }

        //删除生成的文件夹
        File dir = new File(res);
        boolean flag = deleteDir(dir);
        if (flag) {
            // do something
        }
        JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
       return(JSON.toJSONString(jsonRootBean,false));
    }

    public static Object parseObject(String xmindFile) throws DocumentException, ArchiveException, IOException {
        String content = parseJson(xmindFile);
        JsonRootBean jsonRootBean = JSON.parseObject(content, JsonRootBean.class);
        return jsonRootBean;
    }


    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            //递归删除目录中的子目录下
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空，可以删除
        return dir.delete();
    }


    /**
     * @return
     */
    public static String getXmindZenContent(String xmindFile,String extractFileDir) throws IOException, ArchiveException {
        List<String> keys = new ArrayList<>();
        keys.add(xmindZenJson);
        Map<String, String> map = ZipUtils.getContents(keys, xmindFile,extractFileDir);
        String content = map.get(xmindZenJson);
       // content = content.substring(1, content.lastIndexOf("]"));

        content = XmindZen.getContent(content);
        return content;
    }

    /**
     * @return
     */
    public static String getXmindLegacyContent(String xmindFile,String extractFileDir) throws IOException, ArchiveException, DocumentException {
        List<String> keys = new ArrayList<>();
        keys.add(xmindLegacyContent);
        keys.add(xmindLegacyComments);
        Map<String, String> map = ZipUtils.getContents(keys, xmindFile,extractFileDir);

        String contentXml = map.get(xmindLegacyContent);
        String commentsXml = map.get(xmindLegacyComments);
        String xmlContent = XmindLegacy.getContent(contentXml, commentsXml);

        return xmlContent;
    }


    private static boolean isXmindZen(String res, String xmindFile) throws IOException, ArchiveException {
        //解压
        File parent = new File(res);
        if (parent.isDirectory()) {
            String[] files = parent.list(new ZipUtils.FileFilter());
            for (int i = 0; i < Objects.requireNonNull(files).length; i++) {
                if (files[i].equals(xmindZenJson)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 如果xmind有概要 需要手动把概要copy为子主题一一关联
     * @param args
     * @throws IOException
     * @throws ArchiveException
     * @throws DocumentException
     */
    public static void main(String[] args) throws IOException, ArchiveException, DocumentException {
        String fileName = "C:\\\\Users\\宋玉\\\\Desktop\\sprint63.xmind";
        String res = parseJson(fileName);
        JsonRootBean jsonRootBean = JSON.parseObject(res, JsonRootBean.class);
        RootTopic rootTopic = jsonRootBean.getRootTopic();
        RootTopic topic = jsonRootBean.getRootTopic();
        Children first = rootTopic.getChildren();
        //System.out.println(jsonRootBean);

        List<String> newTitles = new ArrayList<>();
        newTitles.add("主题,优先级,sprint,模块,标题,描述,步骤,预期结果");
        String name = topic.getTitle();
        getLoopTopicName(newTitles,"", 2,2, first);
        for (int i = 1; i < newTitles.size(); i++) {
            String format = String.format("%s,%s,%s,%s", "Medium: P2", name,"移动应用 销售", newTitles.get(i));
            String[] split = format.split(SEMMA);
            String[] split1 = new String[7];
            for (int j = 0; j < split.length; j++) {
                split1[j] = split[j];
                if (j==3 && split.length > 4){
                    split1[j] = split[j] + "-" + split[j+1];
                }
            }
            split1[6] = split[split.length-1];
            split1[5] = split1[4];
            if (StringUtils.isEmpty(split1[6])){
                split1[6] = split[split.length-2];
            }
            format = String.join(SEMMA, split1);
            format = "鸿蒙,"+format;
            newTitles.set(i,format);
        }
        String csvName = name + "-" +System.currentTimeMillis();
        Path path = Paths.get(fileName);
        String newPath = path.getParent().toString() +"\\"+csvName+".csv";

        //FileUtils.writeLines(new File(newPath),"UTF-8",newTitles);
        try(FileOutputStream fos = new FileOutputStream(newPath, false);){
            byte[] uft8bom = {(byte) 0xef, (byte) 0xbb, (byte) 0xbf};
            fos.write(uft8bom);
            //按行写出
            for (int i = 0; i < newTitles.size(); i++) {
                String s = newTitles.get(i).replace("null", "");
                byte[] bytes = s.getBytes("UTF8");
                if (i != 0) {
                    fos.write("\r\n".getBytes());
                }
                fos.write(bytes);
            }
        }

//        writeByteArrayToFile
//        CsvWriter writer = CsvUtil.getWriter(new File(newPath), CharsetUtil.CHARSET_UTF_8, true, CsvWriteConfig.defaultConfig().setAlwaysDelimitText(true));
//        //按行写出
//        for (String newTitle : newTitles) {
//            writer.write(new String[]{newTitle});
//            writer.writeLine();
//        }
    }

    public static void getLoopTopicName(List<String> newTitles,String name,int loop,int length,Children first){
        if (null == first || null == first.getAttached()){
            name = String.join(SEMMA, name, "");
            newTitles.add(name);
        }else{
//        if (null == first){
//            first = new Children();
//        }
//        if (null == first.getAttached()){
//            Attached attached = new Attached();
//            first.setAttached(Arrays.asList(attached));
//        }
        if (loop > 0){
            int innerLoop = 0;
            for (Attached attached : first.getAttached()) {
                innerLoop = loop;
                Children children = attached.getChildren();
                String title = getTitle(name, innerLoop, length, attached);
                getLoopTopicName(newTitles,title, --innerLoop,length, children);
            }
            loop = innerLoop;
        }else{
            for (Attached attached : first.getAttached()) {
                Children children = attached.getChildren();
                String title = getTitle(name, loop, length, attached);
                getLoopTopicName2(newTitles,title, children);
            }
        }
        }
    }

    public static void getLoopTopicName2(List<String> newTitles,String name,Children first){
        if (null == first || null == first.getAttached()){
            newTitles.add(name);
        }else{
            for (Attached attached : first.getAttached()) {
                Children children = attached.getChildren();
                String title = getTitle2(name, attached);
                getLoopTopicName2(newTitles,title, children);
            }
        }
    }

    private static String getTitle(String name, int loop, int length, Attached attached) {
        String title = StringUtils.isEmpty(attached.getTitle()) ? "" : attached.getTitle();
        title = title.replace(SEMMA, "，");
        if (loop == length) {
            //title = String.join("-", name, title);
        }else {
            title = String.join(SEMMA, name, title);
        }
//        if (CollectionUtil.isNotEmpty(summary)){
//            String s = summary.get(0).getTitle();
//            s = s.replace(SEMMA, "，");
//            title = String.join(SEMMA, title,s);
//        }
        title = StringUtils.replace(title,"\n"," ; ");
        return title;
    }

    private static String getTitle2(String name, Attached attached) {
        String title = StringUtils.isEmpty(attached.getTitle()) ? "" : attached.getTitle();
        title = title.replace(SEMMA, "，");
        title = String.join("\t", name, title);
//        if (CollectionUtil.isNotEmpty(summary)){
//            String s = summary.get(0).getTitle();
//            s = s.replace(SEMMA, "，");
//            title = String.join(SEMMA, title,s);
//        }
        title = StringUtils.replace(title,"\n"," ; ");
        return title;
    }


}
